#include "ch32x035.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesDelay.h"
#include "DevicesSPI.h"
#include "DevicesQueue.h"
#include "DevicesCi24R1.h"


#define Ci24R1_MOSI_GPIO_Port       GPIOA
#define Ci24R1_MOSI_GPIO_Pin        GPIO_Pin_7

#define CI24R1_CS_HIGH              SPI1_NSS_SET_HIGH
#define CI24R1_CS_LOW               SPI1_NSS_SET_LOW

#define ucCi24R1SpiWriteByte        ucSPI1WriteByte
#define ucCi24R1SpiReadByte         ucSPI1ReadByte
#define cCi24R1SpiWriteDatas        cSPI1WriteDatas
#define cCi24R1SpiReadDatas         cSPI1ReadDatas


void vCi24R1ExitInit(void);
int8_t cCi24R1Check(void);
void vCi24R1IoModeSet(uint32_t uiMosiMode);
void vCi24R1MisoIsrSet(int8_t cIsr);
int8_t cCi24R1WriteCmd(uint8_t ucCmd);
int8_t cCi24R1WriteByte(uint8_t ucAddr, uint8_t ucValue);
uint8_t ucCi24R1ReadByte(uint8_t ucAddr);
int8_t cCi24R1WriteDatas(uint8_t ucAddr, void *pvBuff, int32_t iLength);
int8_t cCi24R1ReadDatas(uint8_t ucAddr, void *pvBuff, int32_t iLength);
void cCi24R1TxMode(void);
void cCi24R1RxMode(void);


/* 设备初始化是否成功 */
static int8_t st_cCi24R1InitState = 0;
static int8_t st_cCi24R1Busy = 0;


void vCi24R1Init(void)
{
    vSPI1Init();

    /* 设置DATA接口为SPI模式 */
    cCi24R1WriteCmd(SELSPI);
    /* CE = 0，进入待机模式 */
    cCi24R1WriteCmd(CE_OFF);

    /* 设备检测 */
    if((st_cCi24R1InitState = (cCi24R1Check() == 0)) != 1)
        return;

    /* 通过先设置 reg0F_selH/L 的值，决定寄存器地址（0x0F）的具体映射 */
    cCi24R1WriteByte(W_REGISTER + EN_RXADDR, 0x01);
    cCi24R1WriteByte(W_REGISTER + EN_AA, 0x81);
    /* 设置模拟电容 16.5pf */
    cCi24R1WriteByte(W_REGISTER + 0x0F, 0xB0);

    /* 使能各管道动态负载长度 */
    cCi24R1WriteByte(W_REGISTER + DYNPD, DPL_P0);

    /* 使能动态负载长度 + 使能命令W_TX_PAYLOAD_NOACK */
    cCi24R1WriteByte(W_REGISTER + FEATURE, EN_DPL | EN_DYN_ACK);

    /* 使能各管道自动确认 */
    cCi24R1WriteByte(W_REGISTER + EN_AA, ENAA_P0);

    /* 使能各管道接收地址 */
    cCi24R1WriteByte(W_REGISTER + EN_RXADDR, ERX_P0);

    /* 地址宽度 */
    cCi24R1WriteByte(W_REGISTER + SETUP_AW, AW_5BYTES);

    /* 设置自动重发延时 + 设备自动重发次数（最大15次） */
    cCi24R1WriteByte(W_REGISTER + SETUP_RETR, ARD_250US | ARC_15);

    /* 设置芯片工作时的信道 */
    cCi24R1WriteByte(W_REGISTER + RF_CH, 97);

    /* 设置射频数据率为250kbps + 9dBm发射功率 */
    cCi24R1WriteByte(W_REGISTER + RF_SETUP, RF_SPEED_250kbps | PWR_3dBm);

    /* 接收模式 */
    cCi24R1RxMode();

    /* 设置DATA接口为IRQ输出模式 */
    cCi24R1WriteCmd(SELIRQ);

    /* 配置 MCU GPIO 外部中断 */
    vCi24R1ExitInit();
}

int8_t cCi24R1Check(void)
{
    const static uint8_t st_ucCi24R1DefAddrs[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
    uint8_t st_ucCi24R1ReadAddrs[5];

    /* 设置发射地址 */
    cCi24R1WriteDatas(W_REGISTER + TX_ADDR, (void *)st_ucCi24R1DefAddrs, 5);
    /* 设置接收地址 */
    cCi24R1WriteDatas(W_REGISTER + RX_ADDR_P0, (void *)st_ucCi24R1DefAddrs, 5);
    /* 读取发射地址 */
    cCi24R1ReadDatas(R_REGISTER + TX_ADDR, st_ucCi24R1ReadAddrs, 5);

    if(memcmp(st_ucCi24R1ReadAddrs, (void *)st_ucCi24R1DefAddrs, 5) != 0)
        return 1;

    return 0;
}

void vCi24R1ExitInit(void)
{
    EXTI_InitTypeDef EXTI_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7);

    EXTI_InitStructure.EXTI_Line = EXTI_Line7;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    EXTI_ClearITPendingBit(EXTI_Line7);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI7_0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* 配置MCU数据引脚为  GPIO 中断模式 */
    vCi24R1MisoIsrSet(1);
}

void vCi24R1IoModeSet(uint32_t uiMosiMode)
{
    /* 设置为上拉输入、复用推挽输出模式 */
    Ci24R1_MOSI_GPIO_Port->OUTDR |= GPIO_Pin_7;
    Ci24R1_MOSI_GPIO_Port->CFGLR &= ~(3 << (7 * 4));
    Ci24R1_MOSI_GPIO_Port->CFGLR |= (!uiMosiMode) << (7 * 4);
}

void vCi24R1MisoIsrSet(int8_t cIsr)
{
    if(cIsr != 0)
    {
        vCi24R1IoModeSet(1);
        EXTI_ClearITPendingBit(EXTI_Line7);
        NVIC_EnableIRQ(EXTI7_0_IRQn);
    }
    else
    {
        NVIC_DisableIRQ(EXTI7_0_IRQn);
    }
}

int8_t cCi24R1IoRead(void)
{
    vCi24R1IoModeSet(1);

    return GPIO_ReadInputDataBit(Ci24R1_MOSI_GPIO_Port, Ci24R1_MOSI_GPIO_Pin);
}

int8_t cCi24R1WriteCmd(uint8_t ucCmd)
{
    CI24R1_CS_LOW();

    /* 配置MCU数据引脚为  SPI 模式 */
    vCi24R1IoModeSet(0);

    ucCi24R1SpiWriteByte(ucCmd);

    CI24R1_CS_HIGH();

    return 0;
}

int8_t cCi24R1WriteByte(uint8_t ucAddr, uint8_t ucValue)
{
    CI24R1_CS_LOW();

    /* 配置MCU数据引脚为  SPI 模式 */
    vCi24R1IoModeSet(0);

    ucCi24R1SpiWriteByte(ucAddr);
    ucCi24R1SpiWriteByte(ucValue);

    CI24R1_CS_HIGH();

    return 0;
}

uint8_t ucCi24R1ReadByte(uint8_t ucAddr)
{
    uint8_t ucValue;

    CI24R1_CS_LOW();

    /* 配置MCU数据引脚为  SPI 模式 */
    vCi24R1IoModeSet(0);

    ucCi24R1SpiWriteByte(ucAddr);

    /* 配置MCU数据引脚为  GPIO 普通上拉输入模式 */
    vCi24R1IoModeSet(1);

    ucValue = ucCi24R1SpiReadByte();

    CI24R1_CS_HIGH();

    return ucValue;
}

int8_t cCi24R1WriteDatas(uint8_t ucAddr, void *pvBuff, int32_t iLength)
{
    int8_t cError;

    CI24R1_CS_LOW();

    /* 配置MCU数据引脚为  SPI 模式 */
    vCi24R1IoModeSet(0);

    ucCi24R1SpiWriteByte(ucAddr);
    cError = cCi24R1SpiWriteDatas(pvBuff, iLength);

    CI24R1_CS_HIGH();

    return cError;
}

int8_t cCi24R1ReadDatas(uint8_t ucAddr, void *pvBuff, int32_t iLength)
{
    int8_t cError;

    CI24R1_CS_LOW();

    /* 配置MCU数据引脚为  SPI 模式 */
    vCi24R1IoModeSet(0);

    ucCi24R1SpiWriteByte(ucAddr);

    /* 配置MCU数据引脚为  GPIO 普通上拉输入模式 */
    vCi24R1IoModeSet(1);

    cError = cCi24R1SpiReadDatas(pvBuff, iLength);

    CI24R1_CS_HIGH();

    return cError;
}

void cCi24R1TxMode(void)
{
    /* 设置DATA接口为SPI模式 */
    cCi24R1WriteCmd(SELSPI);

    /* CE = 0，返回待机模式 */
    cCi24R1WriteCmd(CE_OFF);

    /* 开启接收中断、发射中断、最大重发计数中断 + 使能CRC + 1Byte CRC + 进入待机模式 + 发射模式 */
    cCi24R1WriteByte(W_REGISTER + CONFIG, EN_CRC | CRCO | PWR_UP);

    /* 清空TX FIFO */
    cCi24R1WriteCmd(FLUSH_TX);

    /* CE = 1，进入发送空闲模式 */
    cCi24R1WriteCmd(CE_ON);
}

void cCi24R1RxMode(void)
{
    /* 设置DATA接口为SPI模式 */
    cCi24R1WriteCmd(SELSPI);

    /* CE = 0，返回待机模式 */
    cCi24R1WriteCmd(CE_OFF);

    /* 使能各管道接收地址 */
    cCi24R1WriteByte(W_REGISTER + EN_RXADDR, ERX_P0);

    /* 开启接收中断、发射中断、最大重发计数中断 + 使能CRC + 1Byte CRC + 进入待机模式 + 接收模式 */
    cCi24R1WriteByte(W_REGISTER + CONFIG, EN_CRC | CRCO | PWR_UP | PRIM_RX);

    /* 清空RX FIFO */
    cCi24R1WriteCmd(FLUSH_RX);

    /* CE = 1，进入接收模式 */
    cCi24R1WriteCmd(CE_ON);
}

static int8_t cCi24R1SendFrame(void *pvBuff, int32_t iLength)
{
    uint8_t ucState;

    /* 读取发射FIFO是否已满 */
    while((ucState = ucCi24R1ReadByte(R_REGISTER + FIFO_STATUS)) & TX_FULL_1);

    /* 写入数据到FIFO */
    cCi24R1WriteDatas(W_TX_PAYLOAD_NOACK, pvBuff, iLength);

    /* 设置DATA接口为IRQ输出模式 */
    cCi24R1WriteCmd(SELIRQ);

    /* 发射完成或者发射错误，MISO引脚会自动拉低 */
    while(cCi24R1IoRead() != 0);

    /* 设置DATA接口为SPI模式 */
    cCi24R1WriteCmd(SELSPI);

    /* 读取中断标志 */
    ucState = ucCi24R1ReadByte(R_REGISTER + STATUS);

    /* 清除中断标志 */
    cCi24R1WriteByte(W_REGISTER + STATUS, ucState);

    return 0;
}
 int8_t cCi24R1SendDatas(void *pvBuff, int32_t iLength)
{
    uint8_t *pucBuff = pvBuff;
    int32_t iLengthTemp;

    if(st_cCi24R1InitState == 0)
        return 1;

    if((pvBuff == NULL) || (iLength < 1))
        return 2;

    if(st_cCi24R1Busy != 0)
        return 3;

    st_cCi24R1Busy = 1;

    /* 配置MCU数据引脚为  GPIO 普通模式 */
    vCi24R1MisoIsrSet(DISABLE);

    /* 设置为发射模式 */
    cCi24R1TxMode();

    /* 向FIFO填充数据 */
    while(iLength > 0)
    {
        /* 每个FIFO最大的长度为32Byte */
        iLengthTemp = iLength > 32 ? 32 : iLength;

        /* 写入数据到FIFO */
        cCi24R1SendFrame(pucBuff, iLengthTemp);

        /* 为了给接收端预留足够的接收处理时间 */
        vDelayMs(1.0f);

        pucBuff += iLengthTemp;
        iLength -= iLengthTemp;
    }

    /* 设置为接收模式 */
    cCi24R1RxMode();

    /* 设置DATA接口为IRQ输出模式 */
    cCi24R1WriteCmd(SELIRQ);

    /* 配置MCU数据引脚为  GPIO 中断模式 */
    vCi24R1MisoIsrSet(ENABLE);

    st_cCi24R1Busy = 0;

    return 0;
}

/* 每次读取1个FIFO的数据 */
int8_t cCi24R1ReceiveDatas(void)
{
    uint8_t ucState, ucBuff[32];
    int8_t cError = 0;

    if(st_cCi24R1InitState == 0)
        return 1;

    if(st_cCi24R1Busy != 0)
        return 2;

    st_cCi24R1Busy = 1;

    /* 配置MCU数据引脚为  GPIO 普通模式 */
    vCi24R1MisoIsrSet(DISABLE);

    /* 设置DATA接口为SPI模式 */
    cCi24R1WriteCmd(SELSPI);

    while((ucCi24R1ReadByte(R_REGISTER + FIFO_STATUS) & RX_EMPTY) == 0)
    {
        /* 读取接收到的字节数 */
        ucState = ucCi24R1ReadByte(R_RX_PL_WID);

        /* 从FIFO读取数据 */
        cError = cCi24R1ReadDatas(R_RX_PAYLOAD, ucBuff, ucState);

        /* 把收到的数据存放到 队列 */
        enumQueuePushDatas(&g_TypeQueueCi24R1Read, ucBuff, ucState);
    }

    /* 读取中断标志 */
    ucState = ucCi24R1ReadByte(R_REGISTER + STATUS);

    /* 清除中断标志 */
    cCi24R1WriteByte(W_REGISTER + STATUS, ucState);

    /* 设置DATA接口为IRQ输出模式 */
    cCi24R1WriteCmd(SELIRQ);

    /* 配置MCU数据引脚为  GPIO 中断模式 */
    vCi24R1MisoIsrSet(ENABLE);

    st_cCi24R1Busy = 0;

    return cError;
}
